#include "handle.h"
#include "tools/config.h"
#include "lua/mysql/mysql.h"
#define TOP(x) printf("%d %d\n", __LINE__, lua_gettop(x))

http_handle::http_handle(short &req_type, std::string &req_url,
                         http_head &head, http_param &param,
                         char *req_body, int req_body_len)
{
    m_req_type = req_type;
    m_req_url = req_url;
    m_map_head = head;
    m_map_param = param;
    m_req_body = req_body;
    m_req_body_len = req_body_len;
}

http_handle::~http_handle()
{
}

bool http_handle::init()
{
    m_Lua = luaL_newstate();
    static const luaL_Reg lualibs[] =
        {
            {"base", luaopen_base},
            {"io", luaopen_io},
            {"mysql", luaopen_mysql},
            {NULL, NULL}};
    const luaL_Reg *lib = lualibs;
    for (; lib->func != NULL; lib++)
    {
        //注意这里如果使用的不是requiref，则需要手动在Lua里面调用require "模块名"
        luaL_requiref(m_Lua, lib->name, lib->func, 1);
        lua_settop(m_Lua, 0);
    }
    luaL_openlibs(m_Lua);

    //脚本引用路径设置
    luaL_dostring(m_Lua, config::get()->package_path());

    //执行urls脚本
    int ret = luaL_dofile(m_Lua, config::get()->urls_path());
    if (0 != ret)
    {
        printf("加载路由文件失败，失败原因：%s\n", lua_tostring(m_Lua, -1));
        return false;
    }

    return true;
}

bool http_handle::process()
{

    std::string urls;
    urls = "function response(status, status_info, content, head, cookie)  \
    local res = {status = status or 200,status_info = status_info or 'OK', \
    cookie = cookie or {['test_cookie'] = '测试cookie'},content = content or '', \
    head = head or {['Server'] = 'Weasel v1.0'}}return res end \
    \
    function urls(request) local view_obj = urlpatterns[request.url] \
    local _response = nil if view_obj == nil then \
    return response(404, 'error', '没有找到视图对象') end \
    if (request.type == 1) then _response = view_obj.get(request) \
    elseif (request.type == 2) then _response = view_obj.post(request) \
    elseif (request.type == 3) then _response = view_obj.head(request) \
    elseif (request.type == 4) then _response = view_obj.put(request) \
    elseif (request.type == 5) then _response = view_obj.delete(request) \
    elseif (request.type == 6) then _response = view_obj.options(request) \
    elseif (request.type == 7) then _response = view_obj.trace(request) \
    elseif (request.type == 8) then _response = view_obj.connect(request) \
    elseif (request.type == 9) then _response = view_obj.patch(request) \
    elseif (request.type == 10) then _response = view_obj.propfind(request) \
    elseif (request.type == 11) then _response = view_obj.proppatch(request) \
    elseif (request.type == 12) then _response = view_obj.mkcol(request) \
    elseif (request.type == 13) then _response = view_obj.lock(request) \
    elseif (request.type == 14) then _response = view_obj.unlock(request) \
    elseif (request.type == 15) then _response = view_obj.copy(request) \
    elseif (request.type == 16) then _response = view_obj.move(request) \
    elseif (request.type == 17) then _response = view_obj.link(request) \
    elseif (request.type == 60) then _response = view_obj.undef(request) \
    end return _response end";

    luaL_dostring(m_Lua, urls.c_str());

    call_urls();

    return true;
}

bool http_handle::call_urls()
{
    //获取urls函数
    lua_getglobal(m_Lua, "urls");

    if (0 == lua_isfunction(m_Lua, -1))
    {
        printf("lua error:%s\n", lua_tostring(m_Lua, -1));
    }

    //创建表
    lua_newtable(m_Lua);
    //request.url
    {
        lua_pushstring(m_Lua, "url");
        lua_pushstring(m_Lua, m_req_url.c_str());
        lua_settable(m_Lua, -3);
    }

    //request.type
    {
        lua_pushstring(m_Lua, "type");
        lua_pushinteger(m_Lua, m_req_type);
        lua_settable(m_Lua, -3);
    }

    //request.body
    {
        if (m_req_body_len > 0)
        {
            lua_pushstring(m_Lua, "body");
            lua_pushstring(m_Lua, m_req_body);
            lua_settable(m_Lua, -3);
        }
    }

    //request.head 头
    {
        lua_pushstring(m_Lua, "head");
        lua_newtable(m_Lua);

        auto ite = m_map_head.begin();
        for (; ite != m_map_head.end(); ite++)
        {
            lua_pushstring(m_Lua, ite->first.c_str());
            lua_pushstring(m_Lua, ite->second.c_str());
            lua_settable(m_Lua, -3);
        }

        lua_settable(m_Lua, -3);
    }

    //request.param 头
    {
        lua_pushstring(m_Lua, "param");
        lua_newtable(m_Lua);

        auto ite = m_map_param.begin();
        for (; ite != m_map_param.end(); ite++)
        {
            lua_pushstring(m_Lua, ite->first.c_str());
            lua_pushstring(m_Lua, ite->second.c_str());
            lua_settable(m_Lua, -3);
        }

        lua_settable(m_Lua, -3);
    }

    //执行调用,未作异常处理，待添加
    lua_pcall(m_Lua, 1, 1, 0);

    //获取status
    {
        lua_getfield(m_Lua, -1, "status");
        m_respones.m_status = (int)lua_tonumber(m_Lua, -1);
        lua_pop(m_Lua, 1);
    }

    //获取status_info
    {
        lua_getfield(m_Lua, -1, "status_info");
        m_respones.m_status_info = lua_tostring(m_Lua, -1);
        lua_pop(m_Lua, 1);
    }

    //获取content
    {
        lua_getfield(m_Lua, -1, "content");
        m_respones.m_content = lua_tostring(m_Lua, -1);
        lua_pop(m_Lua, 1);
    }

    //获取head
    {
        lua_getfield(m_Lua, -1, "head");
        //作为Key
        lua_pushnil(m_Lua);
        while (lua_next(m_Lua, -2))
        {
            const char *key = lua_tostring(m_Lua, -2);
            const char *value = lua_tostring(m_Lua, -1);
            m_respones.m_head[key] = value;
            lua_pop(m_Lua, 1);
        }

        lua_pop(m_Lua, 1);
    }

    //获取cookie
    {
        lua_getfield(m_Lua, -1, "cookie");
        //作为Key
        lua_pushnil(m_Lua);
        while (lua_next(m_Lua, -2))
        {
            const char *key = lua_tostring(m_Lua, -2);
            const char *value = lua_tostring(m_Lua, -1);
            m_respones.m_cookie[key] = value;
            lua_pop(m_Lua, 1);
        }
        lua_pop(m_Lua, 1);
    }
    lua_pop(m_Lua, 1);

    return true;
}

http_respones &http_handle::get_respones()
{
    return m_respones;
}